package com.game.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

public class GamePanel extends JPanel implements ActionListener {
    private static final int WIDTH = 600;
    private static final int HEIGHT = 600;
    private static final int UNIT_SIZE = 25;
    private static final int GAME_UNITS = (WIDTH * HEIGHT) / (UNIT_SIZE * UNIT_SIZE);
    private static final int DELAY = 100; // 延迟时间（毫秒）

    private final ArrayList<Point> snakeBody = new ArrayList<>();
    private Point food;
    private char direction = 'R'; // 初始方向为右
    private boolean running = false;
    private Timer timer;
    private Random random;

    public GamePanel() {
        random = new Random();
        this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        this.setBackground(Color.BLACK);
        this.setFocusable(true);
        this.addKeyListener(new MyKeyAdapter());
        startGame();
    }

    public void startGame() {
        snakeBody.clear();
        snakeBody.add(new Point(UNIT_SIZE * 4, UNIT_SIZE * 4)); // 初始位置
        spawnFood();
        running = true;
        timer = new Timer(DELAY, this);
        timer.start();
    }

    public void spawnFood() {
        int x = random.nextInt((WIDTH / UNIT_SIZE)) * UNIT_SIZE;
        int y = random.nextInt((HEIGHT / UNIT_SIZE)) * UNIT_SIZE;
        food = new Point(x, y);
    }

    public void move() {
        for (int i = snakeBody.size() - 1; i > 0; i--) {
            snakeBody.get(i).x = snakeBody.get(i - 1).x;
            snakeBody.get(i).y = snakeBody.get(i - 1).y;
        }

        switch (direction) {
            case 'U' -> snakeBody.get(0).y -= UNIT_SIZE;
            case 'D' -> snakeBody.get(0).y += UNIT_SIZE;
            case 'L' -> snakeBody.get(0).x -= UNIT_SIZE;
            case 'R' -> snakeBody.get(0).x += UNIT_SIZE;
        }
    }

    public void checkCollisions() {
        // 检查蛇是否撞到自己
        for (int i = 1; i < snakeBody.size(); i++) {
            if (snakeBody.get(i).equals(snakeBody.get(0))) {
                running = false;
            }
        }

        // 检查蛇是否撞到边界
        if (snakeBody.get(0).x < 0 || snakeBody.get(0).x >= WIDTH ||
            snakeBody.get(0).y < 0 || snakeBody.get(0).y >= HEIGHT) {
            running = false;
        }

        if (!running) {
            timer.stop();
        }
    }

    public void growSnake() {
        Point lastPoint = snakeBody.get(snakeBody.size() - 1);
        snakeBody.add(new Point(lastPoint.x, lastPoint.y));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        draw(g);
    }

    public void draw(Graphics g) {
        if (running) {
            g.setColor(Color.RED);
            g.fillOval(food.x, food.y, UNIT_SIZE, UNIT_SIZE);

            for (Point point : snakeBody) {
                g.setColor(Color.GREEN);
                g.fillRect(point.x, point.y, UNIT_SIZE, UNIT_SIZE);
            }
        } else {
            gameOver(g);
        }
    }

    public void gameOver(Graphics g) {
        // 游戏结束显示
        g.setColor(Color.RED);
        g.setFont(new Font("Ink Free", Font.BOLD, 75));
        FontMetrics metrics = getFontMetrics(g.getFont());
        g.drawString("Game Over", (WIDTH - metrics.stringWidth("Game Over")) / 2, HEIGHT / 2);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (running) {
            move();
            checkCollisions();
            if (snakeBody.get(0).equals(food)) {
                growSnake();
                spawnFood();
            }
        }
        repaint();
    }

    private class MyKeyAdapter extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
                case KeyEvent.VK_UP:
                    if (direction != 'D') {
                        direction = 'U';
                    }
                    break;
                case KeyEvent.VK_DOWN:
                    if (direction != 'U') {
                        direction = 'D';
                    }
                    break;
                case KeyEvent.VK_LEFT:
                    if (direction != 'R') {
                        direction = 'L';
                    }
                    break;
                case KeyEvent.VK_RIGHT:
                    if (direction != 'L') {
                        direction = 'R';
                    }
                    break;
            }
        }
    }
}